package com.soo.hoo.admin.api;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.soo.hoo.admin.model.entity.SysBook;
import com.soo.hoo.admin.model.entity.SysBookCover;
import com.soo.hoo.admin.model.entity.SysBookReceiving;
import com.soo.hoo.admin.model.entity.SysUserFamily;
import com.soo.hoo.admin.model.vo.BookVO;
import com.soo.hoo.admin.model.vo.FamilyVO;
import com.soo.hoo.admin.service.*;
import com.soo.hoo.admin.utils.SaLoginUtil;
import com.soo.hoo.core.annotation.OperateLog;
import com.soo.hoo.core.enums.BusinessTypeEnum;
import com.soo.hoo.core.enums.OperatorEnum;
import com.soo.hoo.core.exception.GlobalException;
import com.soo.hoo.core.model.MatchItem;
import com.soo.hoo.core.model.Page;
import com.soo.hoo.core.model.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 礼簿管理
 * </p>
 *
 * @author 杨燚
 * @since 2024/4/1
 */
@Tag(name = "礼簿管理")
@RequestMapping("/book/")
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BookController {


    private final BookService bookService;
    private final UserFamilyService userFamilyService;
    private final BookCoverService coverService;
    private final BookReceivingService receivingService;

    @PostMapping("create")
    @Operation(summary = "创建礼簿")
    @OperateLog(title = "创建礼簿", businessType = BusinessTypeEnum.CREATE)
    @Transactional(rollbackFor = GlobalException.class)
    public Result<Void> create(@RequestBody @Valid SysBook book) {
        book.setFamilyId(userFamilyService.getUserFamilyId(StpUtil.getLoginIdAsLong()));
        book.setUserId(StpUtil.getLoginIdAsLong());
        bookService.save(book);
        userFamilyService.setFamily(StpUtil.getLoginIdAsLong(), book.getFamilyId());
        return Result.success();
    }

    @Operation(summary = "分页")
    @PostMapping("page")
    @OperateLog(title = "分页查询", businessType = BusinessTypeEnum.QUERY)
    public Result<Page<BookVO>> page(@RequestBody @Valid Page<SysBook> param) {
        SysUserFamily family = userFamilyService.getFamily(StpUtil.getLoginIdAsLong());
        if (family == null) {
            return Result.success(
                    new Page<>(param.getCurrent(), param.getSize())
            );
        }
        List<String> familyIds = CollUtil.newArrayList(family.getFamilyId());
        if (StrUtil.isNotBlank(family.getFamilyIds())) {
            familyIds.addAll(Arrays.stream(family.getFamilyIds().split(",")).toList());
        }
        MatchItem matchItem = new MatchItem("familyId", familyIds, OperatorEnum.IN, true);
        if (CollUtil.isEmpty(param.getMatchItems())) {
            List<MatchItem> matchItems = ListUtil.of(matchItem);
            param.setMatchItems(matchItems);
        } else {
            param.getMatchItems().add(matchItem);
        }
        Page<SysBook> page = bookService.page(param);
        Page<BookVO> res = new Page<>(page.getCurrent(), page.getSize(), page.getTotal(), page.getPages(), null);
        if (CollUtil.isNotEmpty(page.getRecords())) {
            List<Long> coverIds = page.getRecords().parallelStream().map(SysBook::getCoverId).toList();
            Map<Long, SysBookCover> coverMap = coverService.getBookCoverMap(coverIds);
            List<Long> ids = page.getRecords().parallelStream().map(SysBook::getId).toList();
            Map<Long, List<SysBookReceiving>> recMap = receivingService.listReceiving(ids);
            List<BookVO> vos = page.getRecords().stream().map(e -> {
                BookVO vo = new BookVO();
                BeanUtil.copyProperties(e, vo);
                SysBookCover cover = coverMap.get(e.getCoverId());
                vo.setCoverPath(cover == null ? "" : cover.getCoverPath());
                List<SysBookReceiving> recList = recMap.getOrDefault(e.getId(), new ArrayList<>());
                vo.setReceivingCount(recList.size());
                vo.setReciprocationCount(
                        (int) recList.parallelStream().filter(SysBookReceiving::getReciprocated).count()
                );
                vo.setReceiveAmount(
                        recList.parallelStream().mapToInt(SysBookReceiving::getAmount).sum()
                );
                return vo;
            }).toList();
            res.setRecords(vos);
        }
        return Result.success(res);
    }

    @PostMapping("update")
    @Operation(summary = "修改礼簿")
    @OperateLog(title = "修改礼簿", businessType = BusinessTypeEnum.UPDATE)
    public Result<Void> update(@RequestBody @Valid SysBook book) {
        Long bookId = Optional.of(book.getId()).orElseThrow(
                () -> new GlobalException("修改失败，礼簿标识为空，请联系管理员")
        );
        SysBook sysBook = bookService.getById(bookId);
        if (book.getFamilyId() == null || ObjUtil.notEqual(book.getFamilyId(), sysBook.getFamilyId())) {
            throw new GlobalException("修改失败，礼簿所属家庭不正确，请联系管理员");
        }
        bookService.updateById(book);
        return Result.success();
    }

    @DeleteMapping("delete")
    @Operation(summary = "删除礼簿")
    @OperateLog(title = "删除礼簿", businessType = BusinessTypeEnum.DELETE)
    public Result<Void> delete(@RequestParam Long id) {
        bookService.removeById(id);
        return Result.success();
    }

    @GetMapping("families")
    @Operation(summary = "获取拥有的家庭列表")
    @OperateLog(title = "获取家庭列表", businessType = BusinessTypeEnum.QUERY)
    public Result<List<FamilyVO>> listFamily() {
        SysUserFamily family = userFamilyService.getFamily(StpUtil.getLoginIdAsLong());
        List<FamilyVO> vos = new ArrayList<>();
        if (family != null) {
            if (StrUtil.isNotBlank(family.getFamilyIds())) {
                List<String> otherFamilyIds = StrUtil.split(family.getFamilyIds(), StrUtil.COMMA);
                List<SysUserFamily> otherFamilies = userFamilyService.getFamilyByFamilyId(otherFamilyIds);
                vos = otherFamilies.stream()
                        .map(e -> FamilyVO.builder()
                                .userName(e.getUserName()).familyId(e.getFamilyId()).myFamily(false)
                                .build()
                        ).collect(Collectors.toList());
            }
            vos.add(
                    FamilyVO.builder()
                            .userName(family.getUserName()).familyId(family.getFamilyId()).myFamily(true)
                            .build()
            );
        }
        return Result.success(vos);
    }
}
